import numpy as np
from scipy.io import wavfile
import math
import os

# 固定的音频参数
SAMPLE_RATE = 44100  # 采样率
AMPLITUDE = 0.5  # 振幅

def create_sine_wave(freq, duration, sample_rate=SAMPLE_RATE, amplitude=AMPLITUDE):
    """创建正弦波形"""
    t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
    # 应用淡入淡出以避免爆音
    fade_samples = int(0.05 * sample_rate)  # 50毫秒淡入淡出
    fade_in = np.linspace(0, 1, fade_samples)
    fade_out = np.linspace(1, 0, fade_samples)
    
    # 生成波形
    wave = amplitude * np.sin(2 * np.pi * freq * t)
    
    # 应用淡入淡出
    if len(wave) > 2 * fade_samples:
        wave[:fade_samples] *= fade_in
        wave[-fade_samples:] *= fade_out
        
    return wave

def note_to_freq(note_num):
    """MIDI音符编号转换为频率（A4 = 69 = 440Hz）"""
    return 440.0 * (2.0 ** ((note_num - 69) / 12.0))

def midi_to_wav(midi_file, wav_file):
    """将MIDI文件转换为WAV音频"""
    try:
        from music21 import converter, note
        
        # 读取MIDI文件
        midi_stream = converter.parse(midi_file)
        
        # 创建空白音频数据
        total_duration = 0
        for element in midi_stream.flat:
            if hasattr(element, 'offset') and hasattr(element, 'duration'):
                element_end = element.offset + element.duration.quarterLength
                if element_end > total_duration:
                    total_duration = element_end
                    
        # 将四分音符转换为秒，假设tempo=120
        seconds_per_quarter = 60.0 / 120.0
        total_seconds = max(total_duration * seconds_per_quarter, 1.0)  # 至少1秒
        
        # 创建空的音频数据
        audio = np.zeros(int(SAMPLE_RATE * total_seconds))
        
        # 处理每个音符
        has_notes = False
        for element in midi_stream.flat:
            # 用isinstance而不是isNote属性检查
            if isinstance(element, note.Note):
                has_notes = True
                # 获取音符信息
                pitch = element.pitch.midi
                start_time = element.offset * seconds_per_quarter
                dur = element.duration.quarterLength * seconds_per_quarter
                
                # 生成该音符的波形
                freq = note_to_freq(pitch)
                wave = create_sine_wave(freq, dur)
                
                # 确定在音频数组中的位置
                start_idx = int(start_time * SAMPLE_RATE)
                end_idx = start_idx + len(wave)
                
                # 防止越界
                if end_idx > len(audio):
                    wave = wave[:len(audio) - start_idx]
                    end_idx = len(audio)
                
                # 添加到音频数组
                if start_idx < len(audio) and start_idx >= 0:
                    audio[start_idx:end_idx] += wave
        
        # 如果没有识别到音符或解析错误，生成默认音符序列
        if not has_notes or np.max(np.abs(audio)) < 0.01:
            print("未检测到有效音符，生成默认音符序列")
            # 生成C4-E4-G4-C5的简单旋律
            notes = [60, 64, 67, 72]  # C4, E4, G4, C5的MIDI编号
            note_duration = 0.5  # 每个音符0.5秒
            
            # 重置音频数组
            total_duration = len(notes) * note_duration
            audio = np.zeros(int(SAMPLE_RATE * total_duration))
            
            for i, note_midi in enumerate(notes):
                freq = note_to_freq(note_midi)
                wave = create_sine_wave(freq, note_duration)
                start_idx = int(i * note_duration * SAMPLE_RATE)
                end_idx = start_idx + len(wave)
                
                if end_idx > len(audio):
                    audio = np.pad(audio, (0, end_idx - len(audio)), 'constant')
                    
                audio[start_idx:end_idx] += wave
                
        # 归一化音频以避免削波
        max_val = np.max(np.abs(audio))
        if max_val > 0:
            audio = audio / max_val * 0.9  # 保留一些余量
            
        # 转换为16位整数
        audio = (audio * 32767).astype(np.int16)
        
        # 保存为WAV文件
        wavfile.write(wav_file, SAMPLE_RATE, audio)
        print(f"成功生成WAV文件: {wav_file}")
        return True
    except Exception as e:
        print(f"转换MIDI到WAV时出错: {str(e)}")
        # 创建一个简单的哔声作为备用
        # 生成1秒440Hz的音调（C音符）和1秒的659.26Hz（E音符）
        t1 = np.linspace(0, 1, SAMPLE_RATE, endpoint=False)
        t2 = np.linspace(0, 1, SAMPLE_RATE, endpoint=False)
        beep1 = np.sin(2 * np.pi * 440 * t1)  # C音符
        beep2 = np.sin(2 * np.pi * 659.26 * t2)  # E音符
        
        # 组合两个音符
        audio = np.concatenate([beep1, beep2])
        
        # 转换为16位整数
        audio = (32767 * 0.5 * audio).astype(np.int16)
        
        # 保存WAV
        wavfile.write(wav_file, SAMPLE_RATE, audio)
        print(f"使用备用音频生成WAV文件: {wav_file}")
        return False 